/*	Conventions used by WinApi++

 *	Abreviations are seriously aVOIDed. 

 *	constants are in ALL_CAPS with underscores to seperate words
 *		This is to follow existing convention - and keep with "C" windows api

 *	variables are in all_lower_case with underscores to seperate words
 *		This is to illustrate that variables are in some ways the same as constants, 
 *		and in some ways, exactly opposite

 * Class names and Type names and Function names are ProperCase
 *    This is to follow suit with the "C" windows api (for FunctionNames) and
 *		(for Classes and Types) it seperates them from CONSTANTS.

 *	C and C++ reserved words (like public, private, class, struct...) are left as
 *		they are. I was tempted to make them ProperCase, but I think a lot of
 *		people would hate it and aVOID using the api as a result - so I refrained.
 *		I also refrained because syntax highlighting in many editors wont work
 *		if I Capitolize the reserved words.
 */	

/* This header file mirrors windows.h with all the wrappers for the 
 *	types that would have existed if the Windows API had been written in C++ 
 *	When there were choices to be made, we decided to NOT reinvent 
 *	the wheel.  We tried to preserve the original function names and 
 * parameters modifying them only to keep with the conventions outlined
 * above. We also decided not to create new classes when a suitable native
 * Windows API class was available, thus leaving all the "functionality" to the
 * true API, and being nothing more than a wrapper that adds ++ to the original.
 */

#pragma once
#define STRICT

#include <windows.h>
//#include <windowsx.h>
#include <exception>
#include <eh.h>
#include <commctrl.h>

/*	first, we declare all the classes that are part of WinApi++
 *	so that we can use them in each other's class definitions with out
 *	spending too much time reorganizing the list.
 *
 *	Because order doesnt matter, we go alphabetical
 *	so it is easy to find what we are looking for if need be.
 *	-brent
 */

/*	These are wrapper classes for the handles defined by windows in windef.h the
 *	classes dont replace the handles, they contain them, and encapsilate the
 * functionality. When you pass them around, pass them as handles, but when you 
 * want to do something with it, assign the m_handle value to the class, becuase it
 *	knows how to m_handle error return values and wraps functionality nicely.
 */

class	AcceleratorTable;	// HACCEL
class	Bitmap;				// HBITMAP
class Brush;				// HBRUSH
class	ColorSpace;			//	HCOLORSPACE
class DeviceContext;		// HDC
class OpenGlRenderingContext;	// HGLRC
class Desktop;				// HDESK
class EnhancedMetaFile;	// HENHMETAFILE
class Font;					// HFONT
class	Icon;					// HICON
class	Cursor;				// HCURSOR
class	Menu;					// HMENU
class MetaFile;			// HMETAFILE
class	Instance;			// HINSTANCE
class	Module;				// HMODULE
class Palette;				// HPALETTE
class Pen;					// HPEN
class	Region;				// HRGN
class	Resource;			// HRSRC
// class String // HSTR - I dont use this one, because I see no functions for HSTRs and I want a "String" class to be differnet
class Task;					//HTASK
class WindowStation;		// HWINSTA
class	KeyboardLayout;	// HKL
#if(WINVER >= 0x0500)
class	Monitor;				//HMONITOR
class Terminal;			//HTERMINAL
class WindowsEventHook;	//HWINEVENTHOOK
#endif


/*	These are classes representing all the built in window classes, and wrappers
 * for all the communication messages with each type of window.
 */

class	Window;				// HWND
	class StaticWindow;		// window of predefined class "static"
		class IconStatic;		// Inherits StaticWindow and defines style: SS_ICONS
		class BitmapStatic;	// Inherits StaticWindow and defines style: SS_BITMAP 
	class ButtonWindow;	// window of predefined class "button"
		class CheckBoxButton;	// "button" with style: BS_AUTOCHECKBOX
		class RadioButton;		// "button" with style: BS_AUTORADIOBUTTON
		class GroupBoxButton;	// "button" with style: BS_GROUPBOX - stores one or more mutually exclusive RadioButtons
		class OwnerDrawButton;	// "button" with style: BS_OWNERDRAW
	class EditWindow;		// window of predefined class "listbox"
		class MultiLineEdit;		// "EditWindow" with style: ES_MULTILINE
	class ListBoxWindow;		// window of predefined class "listbox"
	class ComboBoxWindow;	// window of predefined class "combobox"
		class SimpleComboBox;	// "combobox" with style: CBS_SIMPLE
		class DropDownListComboBox;	// "combobox" with style: CBS_DROPDOWNLIST
	class MdiClientWindow;	// window of predefined class "mdiclient"
	class ProgressWindow;	// window of predefined class PROGRESS_CLASS
	class RichEditWindow;	// window of predefined class "richedit"
	class ScrollBarWindow;	// window of predefined class "scrollbar"
		class SizeGropScrollBar;	// "scrollbar" with style: SBS_SIZEGRIP
	class ToolbarWindow;		// window of CommCtrl.h defined type TOOLBARCLASSNAME

/* Sort of built in controls - defined in commctrl.h - they are 
 * part of IE, not Windows itself.
 */
class ImageList;		// HIMAGELIST
class TreeViewWindow;	//window of predefined class WC_TREEVIEW
class	ToolbarWindow;
class ListViewWindow;

/* other stuff that was begging to be wrapped or created in order to make life simple
 */
class Heap;				//	Heap functions wrapped around a generic HANDLE (dont ask me why it isnt an HHEAP, ask ms)
class	Application;	// Inherits HINSTANCENACE, adds functionality for glueing together an EXE 
class	Library;			// HINSTANCE, HMODULE (for loading DLLs)
class	Message;			// MSG, with wrappers for related functions
class Color;			// a COLORREF with some functions tied to it
class	Dialog;        // a wrapper for a dialog box loaded from a resource
class	String;			// LPTSTR wrapper with dynamic auto reallocation and smart memory managment feels like VB string
class	System;			// Wrapper for GetSystemMetrics, GetComputerName, .. and other "system" things

#include <eh++.h>		// all exception handling classes built into api++ and thier inline members

class Heap
{
public:
	Heap();
	~Heap();

	LPVOID	Alloc(SIZE_T);	
	LPVOID	ReAlloc(LPVOID, SIZE_T);
	VOID		Free(LPVOID);				

	VOID		Validate();
	SIZE_T	GetSize(LPVOID);

private:
	HANDLE	m_handle;
};

#include <String++.h> // defines the String class declared above
	
class Instance	
{
public:
	Instance();
	Instance(HINSTANCE);
	operator	HINSTANCE();

	HACCEL	LoadAccelerators(LPTSTR name);
	HACCEL	LoadAccelerators(WORD id);

	HBITMAP	LoadBitmap(LPTSTR name);
	HBITMAP	LoadBitmap(WORD id);

	HCURSOR	LoadCursor(LPTSTR name);
	HCURSOR	LoadCursor(WORD id);

	HICON		LoadIcon(LPTSTR name);
	HICON		LoadIcon(WORD id);

	HMENU		LoadMenu(LPTSTR name);
	HMENU		LoadMenu(WORD id);

protected:
	HINSTANCE	m_handle;
};


class Application : public Instance
{
public:
	BOOL		Initialize(HINSTANCE h_instance, HINSTANCE h_prev_instance, LPSTR cmd_line, INT cmd_show);
	virtual	BOOL	OnInitialize() = 0;
	virtual	VOID	OnTerminate() { /* does nothing if it isnt overridden */ }

	VOID		GenericMessageLoop();
	VOID		GenericMessageLoop(HACCEL table);

   VOID		PostQuitMessage();
   VOID		PostQuitMessage(INT exit_code);

	virtual	VOID	OnUnhandledException(Exception const &e);
	static	VOID	ExceptionTranslator(UINT u, EXCEPTION_POINTERS* pExp);

	INT		GetCmdShow();
	LPTSTR	GetCmdLine();
	VOID		SetExitCode(INT);
	INT		GetExitCode();

private:
	INT		m_cmd_show;
	INT		m_exit_code;
};


#ifdef MAIN_MODULE
	Application *app_base;
#else
	extern Application *app_base;
#endif



class Library : public Instance
{
public:
	Library();

	BOOL		TryLoad(LPCTSTR library_name);
	VOID		Load(LPCTSTR library_name);
	VOID		Free();
};


#if defined(_WIN64)
typedef __int64 LONG_PTR;
#else
typedef long LONG_PTR;
#endif

class Window	
{
protected:
	HWND		m_handle;
	LONG_PTR	GetLongPtr(INT data_id);
	VOID		SetLongPtr(INT data_id, LONG_PTR new_value);
	VOID		SetThisPtr();

public:
//	Constructors, Descrtuctors, and Converters
	Window();
	Window(HWND h_wnd);
	operator	HWND();


// Methods - Do something, and return nothing
	VOID		Create(DWORD ex_style, LPCTSTR class_name, LPCTSTR window_text, DWORD style, INT x, INT y, INT w, INT h, HWND parent, HMENU menu, HINSTANCE instance);
	VOID		Create(LPCTSTR class_name, LPCTSTR window_text, DWORD style, INT x, INT y, INT w, INT h, HWND parent, HMENU menu);
	VOID		Create(LPCTSTR class_name, LPCTSTR window_text, DWORD style, INT w, INT h, HWND parent, HMENU menu);
	VOID		Create(LPCTSTR class_name, LPCTSTR window_text, DWORD style, HWND parent, HMENU menu); 	
	VOID		Create(LPCTSTR class_name, LPCTSTR window_text, DWORD style, HMENU menu); 	
	VOID		Create(LPCTSTR class_name, LPCTSTR window_text, DWORD style);
	VOID		Destroy();

	VOID		Show(INT cmd_show);
	VOID		Show();
	VOID		Minimize();
	VOID		Maximize();
	VOID		Restore();
	VOID		Hide();

	VOID		Enable();
	VOID		Disable();

	VOID		Update();
	HDC		BeginPaint(LPPAINTSTRUCT ps);
	VOID		EndPaint(LPPAINTSTRUCT ps);

	VOID		BringToTop();				//brings to top of Z order for windows in this app, but not other apps
	VOID		Activate();					//brings to front, even over other apps  //via SetForgroundWindow

	VOID		Move(INT x, INT y, INT w, INT h, BOOL repaint = TRUE);
	VOID		Move(HWND insert_after, INT x, INT y, INT w, INT h, UINT flags); //via SetWindowPos

//	Functions	-	change nothing, Discover Something, and return results


//	Property Gets	-	Read Something and do nothing
//	Property Sets	-	Change only the property they set, and return nothing
	VOID		GetText(LPCTSTR buffer, INT buffer_length, INT *return_length);
	VOID		GetText(LPCTSTR buffer, INT buffer_length);
	INT		GetTextLength();
	VOID		SetText(LPCTSTR new_value);
	String	GetText();

	HWND		GetParent();
	VOID		SetParent(HWND);

	VOID		GetClientRect(RECT*);
//	VOID		AdjustRect(RECT*, UINT style, BOOL has_menu);

//	VOID		EnumChildren();

//	HWND		GetRelatedWindow();	//is window
//	BOOL		IsDecendantOf(); //is child

	BOOL		GetIsVisible();
	VOID		SetIsVisible(BOOL);

	BOOL		GetIsEnabled();
	VOID		SetIsEnabled(BOOL);

	BOOL		GetIsUnicode();
	BOOL		GetIsMinimized();
	BOOL		GetIsMaximized();
	BOOL		GetIsNormalSized();
	
	VOID		SetPlacement(CONST WINDOWPLACEMENT *);
	VOID		GetPlacement(WINDOWPLACEMENT *);

	HMENU		GetMenu();
	VOID		SetMenu(HMENU);
};

/*
class Dialog : public Window
{
public:
	INT		PromptFromResource(INT resource_id, Window* parent, DLGPROC dlg_proc);
	VOID		EndPrompt(INT return_value);
	VOID		EndPrompt()			{	EndPrompt(0);	}
};
*/

class Message : public MSG
{
public:
	Message();

	BOOL		Get();
	BOOL		Get(HWND h_wnd);
	BOOL		Get(UINT msg_filter_min, UINT msg_filter_max);
	BOOL		Get(HWND h_wnd, UINT msg_filter_min, UINT msg_filter_max);
	BOOL		Translate();
	LONG		Dispatch();
};


class AcceleratorTable	
{
protected:
	HACCEL	m_handle;

public:
	AcceleratorTable();
	AcceleratorTable(HACCEL);
	operator	HACCEL();

	BOOL		Translate(LPMSG);
	VOID		Destroy();
};


class DeviceContext
{
protected:
	HDC		m_handle;

public:
	DeviceContext();
	DeviceContext(HDC);
	operator	HDC();

	INT		DrawText(LPCTSTR text, INT text_length, LPRECT rect, UINT format_flags = DT_TOP | DT_LEFT);
	VOID		DrawIcon(INT x, INT y, HICON);
	VOID		DrawIcon(INT x, INT y, HIMAGELIST, INT index, UINT sytle = ILD_NORMAL);
};


class Bitmap	
{
protected:
	HBITMAP	m_handle;

public:
	Bitmap();			
	Bitmap(HBITMAP);	
	operator	HBITMAP();

	VOID		Destroy();
	VOID		Load(HINSTANCE, WORD resource_id);
	VOID		Load(WORD resource_id); //assumes app_base->h_instance
	VOID		Load(HINSTANCE, LPCTSTR resource_name);
	VOID		Load(LPCTSTR resource_name); //assumes app_base->h_instance
	VOID		LoadFromSystem(WORD stock_resource_id);
};

class Icon	
{
protected:
	HICON		m_handle;

public:
	Icon();
	Icon(HICON);
	operator	HICON();

	VOID		Create(/* this needs help */);
	VOID		Create(ICONINFO);
	VOID		Destroy();
	HICON		Copy();
	HICON		Duplicate();
	VOID		Extract(LPCTSTR path, UINT index);
	VOID		Load(HINSTANCE, WORD resource_id);
	VOID		Load(WORD resource_id); //assumes app_base->h_instance
	VOID		LoadFromSystem(WORD stock_resource_id);

	BOOL		GetIsCursor();
	BOOL		GetIsIcon();
	HBITMAP	GetMask();
	HBITMAP	GetBitmap();
};

class Cursor : public Icon
{
public:
	Cursor();
	Cursor(HCURSOR);
	operator	HCURSOR();

	VOID		Load(HINSTANCE, WORD resource_id);
	VOID		Load(WORD resource_id);				//assumes app_base->h_instance
	VOID		Load(HINSTANCE, LPCTSTR resource_name);
	VOID		Load(LPCTSTR resource_name);		//assumes app_base->h_instance
	VOID		LoadFromSystem(WORD stock_resource_id);

	VOID		Destroy();
	VOID		GetHotspot(POINT);
	DWORD		GetHotspotX();
	DWORD		GetHotspotY();
};

class Menu	
{
protected:
	HMENU		m_handle;

public:
	Menu();
	Menu(HMENU);
	operator	HMENU();

	VOID		Load(HINSTANCE, WORD resource_id);
	VOID		Load(WORD resource_id); //assumes app_base->h_instance
	VOID		Load(HINSTANCE, LPCTSTR resource_name);
	VOID		Load(LPCTSTR resource_name); //assumes app_base->h_instance

	VOID		Create();
	VOID		Destroy();
	VOID		Insert(UINT identifier, BOOL by_position, LPMENUITEMINFO);
	VOID		Insert(UINT position, UINT flags, UINT_PTR new_item_info, LPCTSTR text);
	VOID		InsertStringItem(UINT position, WORD identifier, LPCTSTR text, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertBitmapItem(UINT position, WORD identifier, HBITMAP, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertOwnerDrawItem(UINT position, WORD identifier, LPVOID owner_draw_item_data, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertPopupString(UINT position, HMENU submenu, LPCTSTR text, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertPopupBitmap(UINT position, HMENU submenu, HBITMAP, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertPopupOwnerDraw(UINT position, HMENU submenu, LPVOID owner_draw_item_data, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertSeperator(UINT position);
	VOID		InsertBreak(UINT position, BOOL draw_vertical_line = FALSE);

	VOID		InsertStringItemByCommandId(UINT command_id, WORD identifier, LPCTSTR text, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertBitmapItemByCommandId(UINT command_id, WORD identifier, HBITMAP, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertOwnerDrawItemByCommandId(UINT command_id, WORD identifier, LPVOID owner_draw_item_data, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertPopupStringByCommandId(UINT command_id, HMENU submenu, LPCTSTR text, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertPopupBitmapByCommandId(UINT command_id, HMENU submenu, HBITMAP, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertPopupOwnerDrawByCommandId(UINT command_id, HMENU submenu, LPVOID owner_draw_item_data, BOOL enabled = TRUE, BOOL checked = FALSE);
	VOID		InsertSeperatorByCommandId(UINT command_id);
	VOID		InsertBreakByCommandId(UINT command_id, BOOL draw_vertical_line = FALSE);

	VOID		DeleteItem(UINT position);
	VOID		DeleteItemByCommandId(UINT command_id);
	HMENU		GetSubMenu(INT position);

	VOID		SetDefaultItem(UINT position);
	UINT		GetDefaultItemPosition(UINT flags = 0);

	VOID		SetDefaultItemByCommandId(UINT command_id);
	UINT		GetDefaultItemCommandId(UINT flags = 0);

	UINT		TrackPopup(UINT flags, INT x, INT y, HWND owner, LPRECT do_not_cover_area);
};

class Color
{
protected:
	COLORREF	value;

public:
	Color();
	Color(COLORREF);
	Color(COLORREF color1, COLORREF color2, INT blend_percent);
	Color(BYTE r, BYTE g, BYTE b);
	Color(BYTE c, BYTE m, BYTE y, BYTE k);
	operator	COLORREF();

	BYTE		GetRed();
	VOID		SetRed(BYTE);

	BYTE		GetGreen();
	VOID		SetGreen(BYTE);

	BYTE		GetBlue();
	VOID		SetBlue(BYTE);

	BYTE		GetCyan();
	VOID		SetCyan(BYTE);

	BYTE		GetMagenta();
	VOID		SetMagenta(BYTE);

	BYTE		GetYellow();
	VOID		SetYellow(BYTE);

	BYTE		GetBlack();
	VOID		SetBlack(BYTE);

};



class StaticWindow : public Window
{
public:
	UINT		DefaultStyle() { return SS_LEFTNOWORDWRAP; }

	Icon		SetIcon(Icon &icon);
	Icon		GetIcon(Icon &icon);
};



class ButtonWindow : public Window
{
public:
	UINT	DefaultStyle()	{ return WS_CHILD | WS_VISIBLE; }

	INT		GetCheck();
	VOID		SetCheck(INT new_value);
	INT		GetState();
	UINT	SetState(INT new_value);
	VOID		SetStyle(UINT new_value ,BOOL redraw);
	VOID		Click();
};



class	EditWindow : public Window
{
public:
	UINT	DefaultStyle() { return WS_CHILD | WS_VISIBLE ; } 

	VOID		LimitText(INT max_character_count);
	INT		GetLineCount();
	BOOL	GetLine(INT line_index, LPTSTR buffer, INT max_character_count);
	VOID		GetRect(RECT *rect);	
	VOID		SetRect(RECT *rect);
	VOID		SetRectNoPaint(RECT *rect);
	UINT	GetSelection();
	VOID		SetSelection(INT start_character_index, INT end_character_index);
	VOID		ReplaceSelection(LPTSTR replace_with);
	BOOL	GetModify();
	BOOL	SetModify(BOOL new_value);
	BOOL	ScrollCaret();
	INT		LineFromChar(INT character_index);
	INT		LineIndex(INT line_index); // character index or first character in this line
	INT		LineLength(INT line_index);
	VOID		Scroll(INT delta_x, INT delta_y);
	BOOL	CanUndo();
	BOOL	Undo();
	VOID		EmptyUndoBuffer();
	VOID		SetPasswordChar(TCHAR new_value);
	VOID		SetTabStops(INT tab_count, INT* tabs);
	BOOL	FmtLines(BOOL add_eol);
	HLOCAL	GetHandle(); //returns a m_handle to the memory holding the text buffer
	VOID		SetHandle(HLOCAL new_value);
#if (WINVER >= 0x030a)
	INT		GetFirstVisibleLine();
	BOOL	SetReadOnly(BOOL new_value);
	TCHAR	GetPasswordChar();
	VOID		SetWordBreakProc(EDITWORDBREAKPROC new_value);
	EDITWORDBREAKPROC	GetWordBreakProc();
#endif /* WINVER >= 0x030a */
};

class MultiLineEdit : public EditWindow
{

};

class RichEditWindow :	public Window
{

};

class	ScrollBarWindow : public Window
{
public:
	UINT	DefaultStyle()	{ return WS_CHILD | WS_VISIBLE; }

	INT		SetPosition(INT new_value, BOOL redraw);
	INT		GetPosition();
	BOOL	SetRange(INT new_min, INT new_max, BOOL redraw);
	BOOL	GetRange(INT* min, INT* max);
};


class	ListBoxWindow	: public Window
{
public:
	INT		GetCount();
	BOOL	ResetContent();
	INT		AddString(LPTSTR new_item);
	INT		InsertString(INT index, INT new_item);
	INT		AddItemData(LPVOID item_data);
	INT		InsertItemData(INT index, UINT data);
	INT		DeleteString(INT index);
	INT		GetTextLen(INT index);
	INT		GetText(INT index, LPTSTR Buffer);
	UINT	GetItemData(INT index);
	UINT	SetItemData(INT index, UINT data);
	INT		Dir(UINT attribute_mask, LPTSTR path);
#if (WINVER >= 0x030a)
	INT		FindString(INT start_index, LPTSTR find);
	INT		FindItemData(INT start_index, UINT data);
	INT		SetSelection(BOOL select, INT index);
	INT		SelectItemRange(BOOL select, INT first_index, INT last_index);
	INT		GetCurrentSelection();
	INT		SetCurrentSelection(INT index);
	INT		SelectString(INT start_index, LPTSTR find);
	INT		SelectItemData(INT start_index, UINT data);
	INT		GetSelected(INT index);
	INT		GetSelectedCount();
	INT		GetSelectedItems(INT item_count, INT *items);
	INT		GetTopIndex();
	INT		SetTopIndex(INT new_value);
	VOID		SetColumnWidth(INT new_value);
	INT		GetHorizontalExtent();
	VOID		SetHorizontalExtent(INT new_value);
	BOOL	SetTabStops(INT tab_count, INT *tabs);
	INT		GetItemRect(INT index, RECT *rect);
	INT		SetCaretIndex(INT index);
	INT		GetCaretIndex();
	INT		FindStringExact(INT start_index, LPTSTR find);
	INT		SetItemHeight(INT index, INT new_value);
	INT		GetItemHeight(INT index);
#endif  /* WINVER >= 0x030a */
};


class	ComboBoxWindow : public Window
{
public:
	INT		LimitText(INT max_character_count);
	UINT	GetEditSelection();
	INT		SetEditSelection(INT start_character_index, INT end_character_index);
	INT		GetCount();
	INT		ResetContent();
	INT		AddString(LPTSTR new_item);
	INT		InsertString(INT index, LPTSTR new_item);
	INT		AddItemData(UINT data);
	INT		InsertItemData(INT index, UINT data);
	INT		DeleteString(INT index);
	INT		GetListTextLength(INT index);
	INT		GetListText(INT index, LPTSTR buffer);
	UINT	GetItemData(INT index);
	INT		SetItemData(INT index, UINT data);
	INT		FindString(INT start_index, LPTSTR find);
	INT		FindItemData(INT start_index, UINT data);
	INT		GetCurrentSelection();
	INT		SetCurrentSelection(INT index);
	INT		SelectString(INT start_index, LPTSTR find);
	INT		SelectItemData(INT index, UINT data);
	INT		Dir(UINT attribute_mask, LPTSTR path);
	BOOL	ShowDropdown(BOOL show);
#if (WINVER >= 0x030a)
	INT		FindStringExact(INT start_index, LPTSTR find);
	BOOL	GetDroppedState();
	VOID		GetDroppedControlRect(RECT *rect);
	INT		GetItemHeight(INT index);
	INT		SetItemHeight(INT index, INT new_value);
	UINT	GetExtendedUI();
	INT		SetExtendedUI(BOOL new_value); //By default, the F4 key opens or closes the list and the DOWN ARROW changes the current selection. In the extended user interface, the F4 key is disabled and the DOWN ARROW key opens the drop-down list. 
#endif  /* WINVER >= 0x030a */
};

class ImageList
{
public:
	ImageList();
	ImageList(HIMAGELIST);
	ImageList(INT w, INT h, UINT flags = ILC_COLOR, INT initial_alloc_count = 1, INT grow_step = 1);
	ImageList(HIMAGELIST list1, INT index1, HIMAGELIST list2, INT index2, INT dx, INT dy);
	operator HIMAGELIST();

	VOID		SetBackgroungColor(COLORREF);
	VOID		SetDragCursorImage(INT index, INT hotspot_x, INT hotspot_y);
	VOID		SetIconSize(INT w, INT h);

	VOID		Create(INT w, INT h, UINT flags = ILC_COLOR, INT initial_alloc_count = 1, INT grow_step = 1);			
	VOID		Destroy();

	VOID		BeginDrag(INT index, INT hotspot_x, INT hotspot_y);
	VOID		DragEnter(HWND owner, INT x, INT y);
	VOID		DragLeave(HWND owner);
	VOID		DragMove(INT x, INT y);
	VOID		DragShowNolock(BOOL new_value);
	VOID		EndDrag();

	INT		Add(HBITMAP image_bitmap, HBITMAP mask_bitmap);
	INT		Add(HICON);
	INT		Add(HBITMAP image_bitmap, COLORREF mask_color);
	VOID		LoadImage(HINSTANCE, WORD resource_id, INT w, INT grow_step, COLORREF mask, UINT type, UINT flags);
	VOID		LoadImage(HINSTANCE, LPCTSTR resource_name, INT w, INT grow_step, COLORREF mask, UINT type, UINT flags);
	VOID		LoadBitmap(HINSTANCE, WORD resource_id, INT w, INT grow_step, COLORREF mask, UINT flags);
	VOID		LoadBitmap(HINSTANCE, LPCTSTR resource_name, INT w, INT grow_step, COLORREF mask, UINT flags);
	VOID		LoadCursor(HINSTANCE, WORD resource_id, INT w, INT grow_step, COLORREF mask, UINT flags);
	VOID		LoadCursor(HINSTANCE, LPCTSTR resource_name, INT w, INT grow_step, COLORREF mask, UINT flags);
	VOID		LoadIcon(HINSTANCE, WORD resource_id, INT w, INT grow_step, COLORREF mask, UINT flags);
	VOID		LoadIcon(HINSTANCE, LPCTSTR resource_name, INT w, INT grow_step, COLORREF mask, UINT flags);
	VOID		Remove(INT index);
	VOID		RemoveAll();
	VOID		Replace(INT index, HBITMAP image, HBITMAP mask);
	VOID		Replace(INT index, HICON);

	/* these probably belong in the DC object */
	VOID		Draw(INT index, HDC dc, INT x, INT y, UINT style);
	VOID		Draw(INT index, HDC dc, INT x, INT y, INT dx, INT dy, COLORREF background, COLORREF foreground, UINT style);

	HICON		GetIcon(INT index, UINT flags = ILD_NORMAL);
	INT		GetImageCount();
	VOID		GetImageInfo(INT index, IMAGEINFO*);
	
	VOID		SetOverlayImage(INT index, INT overlay);

	VOID		Read(LPSTREAM);
	VOID		Write(LPSTREAM);
};

class ToolbarWindow : public Window
{
protected:
	VOID		SetButtonStructSize();

public:
	VOID		AddBitmap(LPTBADDBITMAP);
	VOID		AddBitmap(HBITMAP);
	VOID		AddBitmap(HINSTANCE, UINT bitmap_resource_id);
	VOID		AddButtons(LPTBBUTTON, UINT count);
	VOID		AddString(HINSTANCE, WORD resource_id);
	VOID		AddStrings(LPCTSTR);
	VOID		AutoSize();
	UINT	GetButtonCount();
	VOID		ChangeBitmap(UINT button_index, UINT image_index);
	VOID		CheckButton(UINT button_index, BOOL new_value = TRUE);
	UINT	CommandToIndex(UINT command_id);
	VOID		Customize();
	VOID		RemoveButton(INT button_index);
	VOID		EnableButton(INT button_index, BOOL new_value = TRUE);
	BOOL	GetIsAnchorHighlightingOn();
	UINT	GetBitmapIndex(INT button_index);
	DWORD	GetBitmapFlags();
	VOID		GetButton(LPTBBUTTON);
	SIZE_T	GetButtonTextLength();
	VOID		GetButtonText(LPTSTR);
	String	GetButtonText();
	VOID		GetColorScheme(LPCOLORSCHEME);
	HIMAGELIST	GetDisabledImageList();
	DWORD	GetStyleEx();
	HIMAGELIST	GetHotImageList();
	INT		GetHotItemIndex();
	HIMAGELIST	GetImageList();
	VOID		GetInsertMark(LPTBINSERTMARK);
	COLORREF	GetInsertMarkColor();
	VOID		GetRectByIndex(INT button_index, LPRECT);
	VOID		GetMaxSize(LPSIZE);
	VOID		GetMaxWidth();
	VOID		GetMaxHeight();
//xp only	VOID		GetMetrics(LPTBMETRICS);
//com only	VOID		GetObject();
	DWORD	GetPadding();
	WORD	GetHorizontalPadding();
	WORD	GetVerticalPadding();
	VOID		GetRectByCommandId(INT id, LPRECT);
	INT		GetRowCount();
	DWORD	GetStateFlags();
/*
GetToolTips
HideButton
Indeterminate
InsertButton
IsButtonChecked
IsButtonEnabled
IsButtonHidden
IsButtonIndeterminate
IsButtonPressed
PressButton
SaveRestore
SetBitmapSize
SetButtonSize
SetCommandId
SetRows
SetState
SetToolTops
*/};


class	System
{
private:
	static	INT		GetMetric(INT metric_id);
	static	COLORREF	GetColor(INT color_id);
	
public:
	static	SIZE_T	GetNameLength();
	static	VOID		GetName(LPTSTR buffer, SIZE_T &buffer_length);

/* GetSystemMetrics Functions */
	static	INT	GetScreenWidth();
	static	INT	GetScreenHeight();
	static	INT	GetVScrollWidth();
	static	INT	GetHScrollHeight();
	static	INT	GetCaptionHeight();
	static	INT	GetBorderWidth();
	static	INT	GetBorderHeight();
	static	INT	GetDialogFrameWidth();
	static	INT	GetDialogFrameHeight();
	static	INT	GetVThumbHeight();
	static	INT	GetHThumbWidth();
	static	INT	GetIconWidth();
	static	INT	GetIconHeight();
	static	INT	GetCursorWidth();
	static	INT	GetCursonHeight();
	static	INT	GetMenuHeight();
	static	INT	GetFullScreenWidth();
	static	INT	GetFullScreenHeight();
	static	INT	GetKanjiWindowHeight();
	static	INT	GetMousePresent();
	static	INT	GetVScrollHeight();
	static	INT	GetHScrollWidth();
	static	INT	GetDebug();
	static	INT	GetSwapButton();
	static	INT	GetReserved1();
	static	INT	GetReserved2();
	static	INT	GetReserved3();
	static	INT	GetReserved4();
	static	INT	GetMinWidth();
	static	INT	GetMinHeight();
	static	INT	GetSizeWidth();
	static	INT	GetSizeHeight();
	static	INT	GetFrameWidth();
	static	INT	GetFrameHeight();
	static	INT	GetMinTrackWidth();
	static	INT	GetMinTrackHeight();
	static	INT	GetDoubleClickWidth();
	static	INT	GetDoubleClickHeight();
	static	INT	GetIconSpacingWidth();
	static	INT	GetIconSpacingHeight();
	static	INT	GetMenuDropAlignment();
	static	INT	GetPenWindows();
	static	INT	GetDoubleByteCharacterSetEnabled();
	static	INT	GetMouseButtonCount();
	static	INT	GetShowSounds();

#if(WINVER >= 0x0400)
	static	INT	GetFixedFrameWidth();
	static	INT	GetFixedFrameHeight();
	static	INT	GetSizeFrameWidth();
	static	INT	GetSizeFrameHeight();
	static	INT	GetSecure();
	static	INT	GetEdgeWidth();
	static	INT	GetEdgeHeight();
	static	INT	GetMinSpacingWidth();
	static	INT	GetMinSpacingHeight();
	static	INT	GetSmallIconHeight();
	static	INT	GetSmallIconWidth();
	static	INT	GetSmallCaptionHeight();
	static	INT	GetSmallSizeWidth();
	static	INT	GetSmallSizeHeight();
	static	INT	GetMenuSizeWidth();
	static	INT	GetMenuSizeHeight();
	static	INT	GetArrange();
	static	INT	GetMinimizedWidth();
	static	INT	GetMinimizedHeight();
	static	INT	GetMaxTrackWidth();
	static	INT	GetMaxTrackHeight();
	static	INT	GetMaximizedWidth();
	static	INT	GetMaximizedHeight();
	static	INT	GetNetwork();
	static	INT	GetCleanBoot();
	static	INT	GetDragWidth();
	static	INT	GetDragHeight();
	static	INT	GetMenuCheckWidth();
	static	INT	GetMenuCheckHeight();
	static	INT	GetSlowMachine();
	static	INT	GetMidEastEnabled();
#endif /* WINVER >= 0x0400 */

#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
	static	INT	GetMouseWheelPresent();
#endif

#if(WINVER >= 0x0500)
	static	INT	GetVirtualScreenLeft();
	static	INT	GetVirtualScreenHeight();
	static	INT	GetVirtualScreenWidth();
	static	INT	GetVirtualScreenHeight();
	static	INT	GetMonitorCount();
	static	INT	GetSameDisplayFormat();
#endif /* WINVER >= 0x0500 */

/* GetSysColor Functions */
   static	Color		GetMessegeBoxControlColor();
   static	Color		GetEditControlColor();
   static	Color		GetListBoxControlColor();
   static	Color		GetButtonControlColor();
   static	Color		GetDialogControlColor();
   static	Color		GetScrollBarControlColor();
   static	Color		GetStaticControlColor();
   static	Color		GetScrollBarColor();
   static	Color		GetBackgroundColor();
   static	Color		GetActiveCaptionColor();
   static	Color		GetInactiveCaptionColor();
   static	Color		GetMenuColor();
   static	Color		GetWindowColor();
   static	Color		GetWindowFrameColor();
   static	Color		GetMenuTextColor();
   static	Color		GetWindowTextColor();
   static	Color		GetCaptionTextColor();
   static	Color		GetActiveBorderColor();
   static	Color		GetInactiveBorderColor();
   static	Color		GetApplicationWorkspaceColor();
   static	Color		GetSelectedBackgroundColor();
   static	Color		GetSelectedTextColor();
   static	Color		GetButtonFaceColor();
   static	Color		GetButtonShadowColor();
   static	Color		GetDisabledTextColor();
   static	Color		GetButtonTextColor();
   static	Color		GetInactiveCaptionTextColor();
   static	Color		GetButtonHighlightColor();

#if(WINVER >= 0x0400)
   static	Color		Get3dDarkShadowColor();
   static	Color		Get3dLightColor();
   static	Color		GetToolTipTextColor();
   static	Color		GetToolTipBackgroundColor();
   static	Color		GetDesktopColor();
   static	Color		Get3dFaceColor();
   static	Color		Get3dShadowColor();
   static	Color		Get3dHighlightColor();
#endif /* WINVER >= 0x0400 */

#if(WINVER >= 0x0500)
   static	Color		GetHotLightColor();
   static	Color		GetGradientActiveCaptionColor();
   static	Color		GetGradientInactiveCaptionColor();
#endif /* WINVER >= 0x0500 */

};


#ifndef	BEGIN_FUNCTION
#ifdef FULL_RELEASE
#define BEGIN_FUNCTION(func_id)
#define END_FUNCTION
#else

#define	BEGIN_FUNCTION(func_id)	\
	const UINT THIS_FUNCTION = func_id;	\
	UINT debug_phase = 0; \
	try \
	{ \


#define	END_FUNCTION \
	}	\
	catch	(Exception e)	\
	{	\
		throw	Exception(THIS_MODULE, THIS_FUNCTION, debug_phase, e);	\
	}	

	
#endif

#define	BEGIN_CALLBACK(func_id) \
	try \
	{	\
		BEGIN_FUNCTION(func_id)

#define	END_CALLBACK	\
		END_FUNCTION	\
	} \
	catch(Exception e) \
	{	\
		MessageBox(NULL, e.what(), "Unhandled Exception:", MB_OK);  \
		terminate();	\
	}	\
	catch(exception e) \
	{	\
		MessageBox(NULL, e.what(), "Unhandled Exception:", MB_OK);  \
		terminate();	\
	}	\
	catch(LPTSTR e) \
	{	\
		MessageBox(NULL, e, "Unhandled Exception:", MB_OK);  \
		terminate();	\
	}	\
	catch(...) \
	{	\
		MessageBox(NULL, "Program execution cannot continue.", "Unhandled Exception:", MB_OK);  \
		terminate();	\
	}

#endif

	

inline	Heap::Heap()
{
	m_handle = ::HeapCreate(HEAP_GENERATE_EXCEPTIONS, 0 ,0);	
}

inline	Heap::~Heap()
{
	if(m_handle) 
	{
		if(::HeapDestroy(m_handle) == 0)	
		{
			m_handle = NULL;	
			throw WindowsError();
		} 
		m_handle = NULL;	
	}	
}

inline	LPVOID	Heap::Alloc(SIZE_T byte_count)
{
	return ::HeapAlloc(m_handle, HEAP_ZERO_MEMORY, byte_count);	
}

inline	VOID	Heap::Free(LPVOID pointer)
{
	if(::HeapFree(m_handle, 0, pointer) == 0) 
	{
		throw WindowsError();
	}
}

inline	SIZE_T	Heap::GetSize(LPVOID pointer)
{
	SIZE_T return_value = ::HeapSize(m_handle, 0, pointer);
   if (return_value ==	(SIZE_T) -1) 
	{
		return 0;  //windows api specifies that there is no extended error info for this function...?
	}
	return return_value;
}

//inline	LPVOID	Heap::ReAlloc(LPVOID pointer, SIZE_T new_byte_count)
//{}

//inline	VOID	Heap::Validate()
//{}


inline	Instance::Instance()
{
	m_handle = NULL;
}

inline	Instance::Instance(HINSTANCE new_value)
{
	m_handle = new_value;
}

inline	Instance::operator HINSTANCE()
{
	return m_handle;
}

inline	HACCEL	Instance::LoadAccelerators(LPTSTR resource_name) 
{
	return ::LoadAccelerators(m_handle, resource_name); 
}

inline	HACCEL	Instance::LoadAccelerators(WORD resource_id) 
{
	return ::LoadAccelerators(m_handle, MAKEINTRESOURCE(resource_id)); 
}

inline	HBITMAP	Instance::LoadBitmap(LPTSTR resource_name) 
{
	return ::LoadBitmap(m_handle, resource_name); 
}

inline	HBITMAP	Instance::LoadBitmap(WORD resource_id) 
{
	return ::LoadBitmap(m_handle, MAKEINTRESOURCE(resource_id)); 
}

inline	HCURSOR	Instance::LoadCursor(LPTSTR resource_name) 
{
	return ::LoadCursor(m_handle, resource_name); 
}

inline	HCURSOR	Instance::LoadCursor(WORD resource_id) 
{
	return ::LoadCursor(m_handle, MAKEINTRESOURCE(resource_id)); 
}


inline	Window::Window()
{
	m_handle = NULL;
}

inline	Window::Window(HWND h_wnd)
{	
	m_handle = h_wnd;	
}

inline	Window::operator	HWND() 
{
	if (this == NULL)	
	{
		return NULL;
	}
	return m_handle;
}

/*inline	INT	Window::GetText(LPTSTR buffer, INT buffer_length)
{
	INT return_value = ::GetWindowText(m_handle, buffer, buffer_length);
	if (return_value == 0 && ::GetLastError() != 0)	
	{
		throw WindowsError();
	}
	return return_value;
}

inline	INT	Window::GetTextLength() 
{
	INT return_value = ::GetWindowTextLength(m_handle);
	if (return_value == 0 && ::GetLastError() != 0)	
	{
		throw WindowsError();
	}
	return return_value;
}

inline	VOID	Window::SetText(LPTSTR new_value)
{
	if (::SetWindowText(m_handle, new_value) == 0)	
	{
		if (::GetLastError() != 0) 
		{
			throw WindowsError();
		}
	}
}
*/
inline	VOID	Window::SetLongPtr(INT data_id, LONG_PTR new_value)
{
	::SetLastError(0);
	if (::SetWindowLong(m_handle, data_id, new_value) == 0 && ::GetLastError() != 0) 
	{
		throw WindowsError();
	}
}

inline	LONG_PTR	Window::GetLongPtr(INT data_id)
{
	::SetLastError(0);
	LONG_PTR return_value = ::GetWindowLong(m_handle, (INT)data_id);
	if (::GetLastError() != 0) 
	{
		throw WindowsError();
	}
	return return_value;
}

inline	VOID	Window::SetThisPtr()
{
	SetLongPtr(GWL_USERDATA, (LONG_PTR)this);
}

inline	VOID	Window::Create(DWORD ex_style, LPCTSTR class_name, LPCTSTR window_text, DWORD style, INT x, INT y, INT w, INT h, HWND parent, HMENU menu, HINSTANCE instance)
{
	m_handle = ::CreateWindowEx(ex_style, class_name, window_text, style, x, y, w, h, parent, menu, instance, (LPVOID)this);
	if (m_handle == NULL) 
	{
		throw WindowsError();
	}
	SetThisPtr();
}

inline	VOID	Window::Create(LPCTSTR class_name, LPCTSTR window_text, DWORD style, INT x, INT y, INT w, INT h, HWND parent, HMENU menu) 
{
	Create(0, class_name, window_text, style, x, y, w, h, parent, menu, app_base->operator HINSTANCE());
}

inline	VOID	Window::Create(LPCTSTR class_name, LPCTSTR window_text, DWORD style, HWND parent, HMENU menu) 
{
	Create(0, class_name, window_text, style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, parent, menu, app_base->operator HINSTANCE());
}

inline	VOID	Window::Create(LPCTSTR class_name, LPCTSTR window_text, DWORD style, HMENU menu) 
{
	Create(0, class_name, window_text, style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, menu, app_base->operator HINSTANCE());
}

inline	VOID	Window::Create(LPCTSTR class_name, LPCTSTR window_text, DWORD style)
{
	Create(0, class_name, window_text, style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, app_base->operator HINSTANCE());
}

inline	Window*	HwndToWindowPtr(HWND h)
{
	::SetLastError(0);
	Window* return_value = (Window*)(LPVOID) ::GetWindowLong(h, GWL_USERDATA);
	if (return_value == NULL && ::GetLastError() != 0) 
	{
		throw WindowsError();
	}
	return return_value;
}

inline	VOID	Window::Destroy()
{
	if (::DestroyWindow(m_handle) == 0) 
	{
		m_handle = NULL;
		throw WindowsError();
	}
	m_handle = NULL;	
}

inline	VOID	Window::Show(INT cmd_show)
{	
	::ShowWindow(m_handle, cmd_show);
}

inline	VOID	Window::Update()
{
	if (::UpdateWindow(m_handle) == 0) 
	{
		throw WindowsError();
	}
}

inline	HDC	Window::BeginPaint(PAINTSTRUCT *ps)
{
	HDC return_value = ::BeginPaint(m_handle, ps);
	if (return_value == NULL)	
	{
		throw WindowsError();
	}
	return return_value;
}

inline	VOID	Window::EndPaint(PAINTSTRUCT *ps)
{
	::EndPaint(m_handle, ps);
}


inline	VOID	Window::GetClientRect(RECT* rect)
{
	if (::GetClientRect(m_handle, rect) == 0)	
	{
		throw WindowsError();
	}
}



inline	Message::Message() 
{
	ZeroMemory((LPVOID)this , sizeof(this)); 
}

inline	BOOL	Message::Get(HWND h_wnd, UINT msg_filter_min, UINT msg_filter_max)
{
	INT return_value = ::GetMessage(this, h_wnd, msg_filter_min, msg_filter_max);
	if (return_value == -1)	
	{
		throw WindowsError();
	}
	return (return_value != 0);
}

inline	BOOL	Message::Get() 
{
	return Get((HWND)NULL, 0, 0);
}

inline	BOOL	Message::Get(HWND h_wnd)
{
	return Get(h_wnd, 0, 0);
}

inline	BOOL	Message::Get(UINT msg_filter_min, UINT msg_filter_max)
{
	return Get((HWND)NULL, msg_filter_min, msg_filter_max);
}

inline	BOOL	Message::Translate()
{
	return (::TranslateMessage(this) != 0);
}

inline	LONG	Message::Dispatch()
{
	return ::DispatchMessage(this);
}





inline	AcceleratorTable::AcceleratorTable() 
{
	AcceleratorTable(0); 
}
	
inline	AcceleratorTable::AcceleratorTable(HACCEL new_value)
{
	m_handle = new_value; 
}
	
inline	BOOL AcceleratorTable::Translate(LPMSG message)	
{
	return ::TranslateAccelerator(message->hwnd, m_handle, message) != 0;
}

inline	AcceleratorTable::operator HACCEL()
{ 
	return m_handle; 
}
	
inline	VOID	AcceleratorTable::Destroy()
{ 
	if (m_handle) 
	{
		if(::DestroyAcceleratorTable(m_handle) == 0) 
		{
			m_handle = NULL; 
			throw WindowsError();
		}			
		m_handle = NULL; 
	} 
}






inline	Bitmap::Bitmap(HBITMAP new_value)
{
	m_handle = new_value; 
}
	
inline	Bitmap::Bitmap() 
{
	Bitmap(0); 
}
	
inline	Bitmap::operator HBITMAP() 
{ 
	return m_handle; 
}
	
inline	VOID	Bitmap::Destroy()
{ 
	if (m_handle) 
	{
		if (::DeleteObject(m_handle) == 0)	
		{
			m_handle = NULL; 
			throw WindowsError();
		}
		m_handle = NULL; 
	} 
}





inline	Cursor::Cursor(HCURSOR new_value)
{
	m_handle = new_value; 
}
	
inline	Cursor::Cursor() 
{
	Cursor(0); 
}
	
inline	Cursor::operator HCURSOR() 
{ 
	return m_handle; 
}
	
inline	VOID	Cursor::Destroy()
{ 
	if (m_handle) 
	{
		::DestroyCursor(m_handle); 
		m_handle = NULL; 
	} 
}






inline	Icon::Icon()
{
	Icon(0); 
}
	
inline	Icon::Icon(HICON new_value)
{
	m_handle = new_value; 
}
	
inline	Icon::operator HICON() 
{ 
	return m_handle; 
}
	
inline	VOID	Icon::Destroy()
{ 
	if (m_handle) 
	{
		::DestroyIcon(m_handle); 
		m_handle = NULL; 
	} 
}






inline	Menu::Menu(HMENU new_value)
{
	m_handle = new_value; 
}
	
inline	Menu::Menu() 
{
	Menu(0); 
}
	
inline	Menu::operator HMENU() 
{ 
	if (this == NULL)	
	{
		return NULL;
	}
	return m_handle; 
}
		
inline	VOID	Menu::Destroy()
{ 
	if (m_handle) 
	{
		if (::DestroyMenu(m_handle) == 0) 
		{
			m_handle = NULL; 
			throw WindowsError();
		}
		m_handle = NULL; 
	} 
}






inline	HICON	Instance::LoadIcon(LPTSTR resource_name) 
{
	HICON return_value = ::LoadIcon(m_handle, resource_name); 
	return return_value;
}
#undef CURRENT_FUNCTION_ID


inline	HICON	Instance::LoadIcon(WORD resource_id) 
{
	return LoadIcon(MAKEINTRESOURCE(resource_id)); 
}

inline	HMENU	Instance::LoadMenu(LPTSTR resource_name) 
{
	return ::LoadMenu(m_handle, resource_name); 
}

inline	HMENU	Instance::LoadMenu(WORD resource_id) 
{
	return ::LoadMenu(m_handle, MAKEINTRESOURCE(resource_id)); 
}


inline	DeviceContext::DeviceContext()
{
	m_handle = NULL;
}

inline	DeviceContext::DeviceContext(HDC new_value)
{
	m_handle = new_value;
}

inline	DeviceContext::operator	HDC()
{
	if (this == NULL)	
	{
		return NULL;
	}
	return m_handle;
}

inline	INT	DeviceContext::DrawText(LPCTSTR text, INT text_length, LPRECT rect, UINT format_flags)
{
	INT return_value = ::DrawText(m_handle, text, text_length, rect, format_flags);		
	if (return_value == 0) 
	{
		throw WindowsError();
	}
	return return_value;
}



inline BOOL	Application::Initialize(HINSTANCE h_instance, HINSTANCE h_prev_instance, LPTSTR cmd_line, INT cmd_show)
{
	m_handle = h_instance;
//	prev_instance = h_prev_instance;
//	m_cmd_line = cmd_line;
	m_cmd_show = cmd_show;
	_set_se_translator(ExceptionTranslator);
	return OnInitialize();
}

inline	VOID	Application::GenericMessageLoop(HACCEL table)
{
	Message message;
	AcceleratorTable accel = table;
	while (message.Get())	{
		if (!accel.Translate(&message)) 
		{
			message.Translate();
			message.Dispatch();
		}
	}
}

inline	VOID	Application::GenericMessageLoop()
{
	Message message;
	while (message.Get())	
	{
		message.Translate();
		message.Dispatch();
	}
}

inline	VOID	Application::PostQuitMessage()
{
	::PostQuitMessage(m_exit_code);  // has no error return
}

inline	VOID	Application::PostQuitMessage(INT exit_code)
{
	m_exit_code = exit_code;
	PostQuitMessage();
}

#ifdef MAIN_MODULE
VOID	Application::ExceptionTranslator(UINT u, EXCEPTION_POINTERS* exp_ptr)
{
	throw WindowsException(u, exp_ptr);
}

VOID	Application::OnUnhandledException(Exception const &e)
{

}
#endif

inline	INT	Application::GetCmdShow()
{
	return m_cmd_show;
}

inline	LPTSTR	Application::GetCmdLine()
{
	return ::GetCommandLine();
}

inline	VOID	Application::SetExitCode(INT new_value)
{
	m_exit_code = new_value;
}

inline	INT	Application::GetExitCode()
{
	return m_exit_code;
}




inline	VOID	Library::Free()
{
	if (m_handle) 
	{
		::FreeLibrary(m_handle);
		m_handle = NULL;
	}
}

inline	VOID	Library::Load(LPCTSTR library_name)
{
	m_handle = ::LoadLibrary(library_name);
}




inline	Color::Color()
{
	value = 0x00000000;	
}

inline	Color::Color(COLORREF new_value)
{
	value = new_value;	
}

inline	Color::operator COLORREF()
{
	return value;	
}






inline INT System::GetMetric(INT metric_id)
{
	INT return_value = ::GetSystemMetrics(metric_id);
	if (return_value == 0)	
	{
		throw WindowsError();
	}
	return return_value;
}

inline COLORREF System::GetColor(INT color_id)
{
	COLORREF return_value = ::GetSysColor(color_id);
	if (return_value == 0)	
	{
		throw WindowsError();
	}
	return return_value;
}
	
inline SIZE_T System::GetNameLength()	
{ 
	return	MAX_COMPUTERNAME_LENGTH + 1; 
}

inline VOID System::GetName(LPTSTR buffer, SIZE_T &buffer_length)	
{
	if (::GetComputerName(buffer, (unsigned long*)&buffer_length) == 0)	
	{
		throw WindowsError(); 
	}
}

/* GetSystemMetrics Functions */
inline INT System::GetScreenWidth()
{
	return GetMetric(SM_CXSCREEN); 
}

inline INT System::GetScreenHeight()
{
	return GetMetric(SM_CYSCREEN); 
}             

inline INT System::GetVScrollWidth()
{ 
	return GetMetric(SM_CXVSCROLL); 
}

inline INT System::GetHScrollHeight()
{ 
	return GetMetric(SM_CYHSCROLL); 
}

inline INT System::GetCaptionHeight()
{ 
	return GetMetric(SM_CYCAPTION); 
}

inline INT System::GetBorderWidth()
{ 
	return GetMetric(SM_CXBORDER); 
}

inline INT System::GetBorderHeight()
{ 
	return GetMetric(SM_CYBORDER); 
}

inline INT System::GetDialogFrameWidth()
{ 
	return GetMetric(SM_CXDLGFRAME); 
}

inline INT System::GetDialogFrameHeight()
{ 
	return GetMetric(SM_CYDLGFRAME); 
}

inline INT System::GetVThumbHeight()
{ 
	return GetMetric(SM_CYVTHUMB); 
}

inline INT System::GetHThumbWidth()
{ 
	return GetMetric(SM_CXHTHUMB); 
}

inline INT System::GetIconWidth()
{ 
	return GetMetric(SM_CXICON); 
}

inline INT System::GetIconHeight()
{ 
	return GetMetric(SM_CYICON); 
}

inline INT System::GetCursorWidth()
{ 
	return GetMetric(SM_CXCURSOR); 
}

inline INT System::GetCursonHeight()
{ 
	return GetMetric(SM_CYCURSOR); 
}

inline INT System::GetMenuHeight()
{ 
	return GetMetric(SM_CYMENU); 
}

inline INT System::GetFullScreenWidth()
{ 
	return GetMetric(SM_CXFULLSCREEN); 
}

inline INT System::GetFullScreenHeight()
{ 
	return GetMetric(SM_CYFULLSCREEN); 
}

inline INT System::GetKanjiWindowHeight()
{ 
	return GetMetric(SM_CYKANJIWINDOW); 
}

inline INT System::GetMousePresent()
{ 
	return GetMetric(SM_MOUSEPRESENT); 
}

inline INT System::GetVScrollHeight()
{ 
	return GetMetric(SM_CYVSCROLL); 
}

inline INT System::GetHScrollWidth()
{ 
	return GetMetric(SM_CXHSCROLL); 
}

inline INT System::GetDebug()
{ 
	return GetMetric(SM_DEBUG); 
}

inline INT System::GetSwapButton()
{ 
	return GetMetric(SM_SWAPBUTTON); 
}

inline INT System::GetReserved1()
{ 
	return GetMetric(SM_RESERVED1); 
}

inline INT System::GetReserved2()
{ 
	return GetMetric(SM_RESERVED2); 
}

inline INT System::GetReserved3()
{ 
	return GetMetric(SM_RESERVED3); 
}

inline INT System::GetReserved4()
{ 
	return GetMetric(SM_RESERVED4); 
}

inline INT System::GetMinWidth()
{ 
	return GetMetric(SM_CXMIN); 
}

inline INT System::GetMinHeight()
{ 
	return GetMetric(SM_CYMIN); 
}

inline INT System::GetSizeWidth()
{ 
	return GetMetric(SM_CXSIZE); 
}

inline INT System::GetSizeHeight()
{ 
	return GetMetric(SM_CYSIZE); 
}

inline INT System::GetFrameWidth()
{ 
	return GetMetric(SM_CXFRAME); 
}

inline INT System::GetFrameHeight()
{ 
	return GetMetric(SM_CYFRAME); 
}

inline INT System::GetMinTrackWidth()
{ 
	return GetMetric(SM_CXMINTRACK); 
}

inline INT System::GetMinTrackHeight()
{ 
	return GetMetric(SM_CYMINTRACK); 
}

inline INT System::GetDoubleClickWidth()
{ 
	return GetMetric(SM_CXDOUBLECLK); 
}

inline INT System::GetDoubleClickHeight()
{ 
	return GetMetric(SM_CYDOUBLECLK); 
}

inline INT System::GetIconSpacingWidth()
{ 
	return GetMetric(SM_CXICONSPACING); 
}

inline INT System::GetIconSpacingHeight()
{ 
	return GetMetric(SM_CYICONSPACING); 
}

inline INT System::GetMenuDropAlignment()
{ 
	return GetMetric(SM_MENUDROPALIGNMENT); 
}

inline INT System::GetPenWindows()
{ 
	return GetMetric(SM_PENWINDOWS); 
}

inline INT System::GetDoubleByteCharacterSetEnabled()
{ 
	return GetMetric(SM_DBCSENABLED); 
}

inline INT System::GetMouseButtonCount()
{ 
	return GetMetric(SM_CMOUSEBUTTONS); 
}

inline INT System::GetShowSounds()
{ 
	return GetMetric(SM_SHOWSOUNDS); 
}

#if(WINVER >= 0x0400)
inline INT System::GetFixedFrameWidth()
{ 
	return GetMetric(SM_CXFIXEDFRAME); 
}

inline INT System::GetFixedFrameHeight()
{ 
	return GetMetric(SM_CYFIXEDFRAME); 
}

inline INT System::GetSizeFrameWidth()
{ 
	return GetMetric(SM_CXSIZEFRAME); 
}

inline INT System::GetSizeFrameHeight()
{ 
	return GetMetric(SM_CYSIZEFRAME); 
}

inline INT System::GetSecure()	
{ 
	return GetMetric(SM_SECURE); 
}

inline INT System::GetEdgeWidth()	
{ 
	return GetMetric(SM_CXEDGE); 
}

inline INT System::GetEdgeHeight()	
{ 
	return GetMetric(SM_CYEDGE); 
}

inline INT System::GetMinSpacingWidth()
{ 
	return GetMetric(SM_CXMINSPACING); 
}

inline INT System::GetMinSpacingHeight()	
{ 
	return GetMetric(SM_CYMINSPACING); 
}

inline INT System::GetSmallIconHeight()
{ 
	return GetMetric(SM_CXSMICON); 
}

inline INT System::GetSmallIconWidth()
{ 
	return GetMetric(SM_CYSMICON); 
}

inline INT System::GetSmallCaptionHeight()
{ 
	return GetMetric(SM_CYSMCAPTION); 
}

inline INT System::GetSmallSizeWidth()
{ 
	return GetMetric(SM_CXSMSIZE); 
}

inline INT System::GetSmallSizeHeight()
{ 
	return GetMetric(SM_CYSMSIZE); 
}

inline INT System::GetMenuSizeWidth()	
{ 
	return GetMetric(SM_CXMENUSIZE); 
}

inline INT System::GetMenuSizeHeight()
{ 
	return GetMetric(SM_CYMENUSIZE); 
}

inline INT System::GetArrange()	
{ 
	return GetMetric(SM_ARRANGE); 
}

inline INT System::GetMinimizedWidth()
{ 
	return GetMetric(SM_CXMINIMIZED); 
}

inline INT System::GetMinimizedHeight()
{ 
	return GetMetric(SM_CYMINIMIZED); 
}

inline INT System::GetMaxTrackWidth()
{ 
	return GetMetric(SM_CXMAXTRACK); 
}

inline INT System::GetMaxTrackHeight()
{ 
	return GetMetric(SM_CYMAXTRACK); 
}

inline INT System::GetMaximizedWidth()
{ 
	return GetMetric(SM_CXMAXIMIZED); 
}

inline INT System::GetMaximizedHeight()
{ 
	return GetMetric(SM_CYMAXIMIZED); 
}

inline INT System::GetNetwork()	
{ 
	return GetMetric(SM_NETWORK); 
}

inline INT System::GetCleanBoot()
{ 
	return GetMetric(SM_CLEANBOOT); 
}

inline INT System::GetDragWidth()
{ 
	return GetMetric(SM_CXDRAG); 
}

inline INT System::GetDragHeight()	
{ 
	return GetMetric(SM_CYDRAG); 
}

inline INT System::GetMenuCheckWidth()
{ 
	return GetMetric(SM_CXMENUCHECK); 
}

inline INT System::GetMenuCheckHeight()
{ 
	return GetMetric(SM_CYMENUCHECK); 
}

inline INT System::GetSlowMachine()
{ 
	return GetMetric(SM_SLOWMACHINE); 
}

inline INT System::GetMidEastEnabled()
{ 
	return GetMetric(SM_MIDEASTENABLED); 
}

#endif /* WINVER >= 0x0400 */

#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
inline INT System::GetMouseWheelPresent()
{ 
	return GetMetric(SM_MOUSEWHEELPRESENT); 
}

#endif

#if(WINVER >= 0x0500)
inline INT System::GetVirtualScreenLeft()
{ 
	return GetMetric(SM_XVIRTUALSCREEN); 
}

inline INT System::GetVirtualScreenHeight()
{ 
	return GetMetric(SM_YVIRTUALSCREEN); 
}

inline INT System::GetVirtualScreenWidth()
{ 
	return GetMetric(SM_CXVIRTUALSCREEN); 
}

inline INT System::GetVirtualScreenHeight()	
{ 
	return GetMetric(SM_CYVIRTUALSCREEN); 
}

inline INT System::GetMonitorCount()
{ 
	return GetMetric(SM_CMONITORS); 
}

inline INT System::GetSameDisplayFormat()
{ 
	return GetMetric(SM_SAMEDISPLAYFORMAT); 
}

#endif /* WINVER >= 0x0500 */

/* GetSysColor Functions */
inline Color System::GetMessegeBoxControlColor()
{ 
	return GetColor(CTLCOLOR_MSGBOX); 
}

inline Color System::GetEditControlColor()
{ 
	return GetColor(CTLCOLOR_EDIT); 
}

inline Color System::GetListBoxControlColor()
{ 
	return GetColor(CTLCOLOR_LISTBOX); 
}

inline Color System::GetButtonControlColor()
{ 
	return GetColor(CTLCOLOR_BTN); 
}

inline Color System::GetDialogControlColor()
{ 
	return GetColor(CTLCOLOR_DLG); 
}

inline Color System::GetScrollBarControlColor()
{ 
	return GetColor(CTLCOLOR_SCROLLBAR); 
}

inline Color System::GetStaticControlColor()
{ 
	return GetColor(CTLCOLOR_STATIC); 
}

inline Color System::GetScrollBarColor()
{ 
	return GetColor(COLOR_SCROLLBAR); 
}

inline Color System::GetBackgroundColor()
{ 
	return GetColor(COLOR_BACKGROUND); 
}

inline Color System::GetActiveCaptionColor()
{ 
	return GetColor(COLOR_ACTIVECAPTION); 
}

inline Color System::GetInactiveCaptionColor()
{ 
	return GetColor(COLOR_INACTIVECAPTION); 
}

inline Color System::GetMenuColor()
{ 
	return GetColor(COLOR_MENU); 
}

inline Color System::GetWindowColor()
{ 
	return GetColor(COLOR_WINDOW); 
}

inline Color System::GetWindowFrameColor()
{ 
	return GetColor(COLOR_WINDOWFRAME); 
}

inline Color System::GetMenuTextColor()
{ 
	return GetColor(COLOR_MENUTEXT); 
}

inline Color System::GetWindowTextColor()
{ 
	return GetColor(COLOR_WINDOWTEXT); 
}

inline Color System::GetCaptionTextColor()
{ 
	return GetColor(COLOR_CAPTIONTEXT); 
}

inline Color System::GetActiveBorderColor()
{ 
	return GetColor(COLOR_ACTIVEBORDER); 
}

inline Color System::GetInactiveBorderColor()
{ 
	return GetColor(COLOR_INACTIVEBORDER); 
}

inline Color System::GetApplicationWorkspaceColor()
{ 
	return GetColor(COLOR_APPWORKSPACE); 
}

inline Color System::GetSelectedBackgroundColor()
{ 
	return GetColor(COLOR_HIGHLIGHT); 
}

inline Color System::GetSelectedTextColor()
{ 
	return GetColor(COLOR_HIGHLIGHTTEXT); 
}

inline Color System::GetButtonFaceColor()
{ 
	return GetColor(COLOR_BTNFACE); 
}

inline Color System::GetButtonShadowColor()
{ 
	return GetColor(COLOR_BTNSHADOW); 
}

inline Color System::GetDisabledTextColor()
{ 
	return GetColor(COLOR_GRAYTEXT); 
}

inline Color System::GetButtonTextColor()
{ 
	return GetColor(COLOR_BTNTEXT); 
}

inline Color System::GetInactiveCaptionTextColor()
{ 
	return GetColor(COLOR_INACTIVECAPTIONTEXT); 
}

inline Color System::GetButtonHighlightColor()
{ 
	return GetColor(COLOR_BTNHIGHLIGHT); 
}


#if(WINVER >= 0x0400)
inline Color System::Get3dDarkShadowColor()
{ 
	return GetColor(COLOR_3DDKSHADOW);
}

inline Color System::Get3dLightColor()
{ 
	return GetColor(COLOR_3DLIGHT); 
}

inline Color System::GetToolTipTextColor()
{ 
	return GetColor(COLOR_INFOTEXT); 
}

inline Color System::GetToolTipBackgroundColor()
{ 
	return GetColor(COLOR_INFOBK); 
}

inline Color System::GetDesktopColor()
{ 
	return GetColor(COLOR_DESKTOP); 
}

inline Color System::Get3dFaceColor()
{ 
	return GetColor(COLOR_3DFACE); 
}

inline Color System::Get3dShadowColor()
{ 
	return GetColor(COLOR_3DSHADOW); 
}

inline Color System::Get3dHighlightColor()
{ 
	return GetColor(COLOR_3DHIGHLIGHT); 
}

#endif /* WINVER >= 0x0400 */

#if(WINVER >= 0x0500)
inline Color System::GetHotLightColor()
{ 
	return GetColor(COLOR_HOTLIGHT); 
}

inline Color System::GetGradientActiveCaptionColor()
{ 
	return GetColor(COLOR_GRADIENTACTIVECAPTION); 
}

inline Color System::GetGradientInactiveCaptionColor()
{ 
	return GetColor(COLOR_GRADIENTINACTIVECAPTION); 
}

#endif /* WINVER >= 0x0500 */













#define DEFINE_WNDPROC(WindowClass, this_function_id)  \
LRESULT CALLBACK	WindowClass::WndProc(HWND h_wnd, UINT message, WPARAM w_param, LPARAM l_param) \
{ \
	BEGIN_CALLBACK(this_function_id)	\
	LRESULT return_value = 0;		\
	WindowClass* window = (WindowClass*)HwndToWindowPtr(h_wnd);      \
	switch (message) \
	{

#define MESSAGE_HANDLER(msg, fn)    \
		case (msg): \
			ON_##msg(fn); \
			return return_value;

#define START_WM_COMMAND	\
		case WM_COMMAND: \
			switch (LOWORD(w_param))  \
			{

/* VOID Cls::OnCommand_<SubCommand>(Window child_window, UINT notification_code) */
#define WM_COMMAND_SUBHANDLER(control_id, fn) \
			case (control_id): \
				window->fn((HWND)(l_param), (UINT)HIWORD(w_param)); \
				return_value = 0; \
				return return_value; 

#define END_WM_COMMAND	\
			} \
			return_value = 0; \
			return return_value; 

#define END_WNDPROC   \
	}	\
	window = NULL;	\
	return ::DefWindowProc(h_wnd, message, w_param, l_param);	\
	END_CALLBACK	\
}



#define DEFINE_DLGPROC(DialogClass)  \
BOOL CALLBACK DialogClass::DlgProc(HWND h_wnd, UINT message, WPARAM w_param, LPARAM l_param) \
{ \
	BOOL return_value = 0;		\
	DialogClass* window = (DialogClass*)HwndToWindowPtr(h_wnd);      \
	switch (message) \
	{

#define END_DLGPROC   \
	}	\
	window = NULL;	\
	return FALSE;	\
}


/* VOID Cls::OnCompacting(InsignedInteger compact_ratio) */
#define ON_WM_COMPACTING(fn) \
		window->fn((UINT)(w_param)); \
		return_value = 0;

#define ON_WM_PAINT(fn)	\
		window->fn(); \
		return_value = 0;

/* VOID Cls::OnCommand(INT control_id, Window child_window, UINT notification_code) */
#define ON_WM_COMMAND(fn) \
			window->fn(LOWORD(wParam), (HWND)(lParam), (UINT)HIWORD(wParam)); \
			return_value = 0

#define ON_WM_DESTROY(fn)	\
		window->fn(); \
		return_value = 0;


